﻿#include "CServerListenerModule.h"
#include "CMsg.h"
#include "CSocketMisc.h"
#include "../game/MsgID.h"
#include "../game/MsgStruct.h"

#include <string.h>
#include <stdio.h>
#include <process.h>

#define TS_DEBUG(fmt, ...) printf("%s:%d fn:%s " fmt "\n", strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__);
#define DEBUG_LOG		printf
#define RCV_BUFF_SIZE	2048

static char _rcv_buf[RCV_BUFF_SIZE] = {0};

static int receive_data(CServerListenerModule* thes, SOCKET* ps) {
	int readSizeByte = 0;
	int nowIdx = 0;
	CMsg* msg = 0;
	CModule* e = thes->msg_executer;

	memset(_rcv_buf, 0, sizeof(_rcv_buf));
	readSizeByte = recv(*ps, _rcv_buf, RCV_BUFF_SIZE, 0);
	while (nowIdx != readSizeByte) {
		msg = (CMsg*)(&_rcv_buf[nowIdx]);
		nowIdx += (msg->data_len + sizeof(CMsg));
		e->sendMsg(e, msg);
	}
	return 0;
}

static int on_new_client_connect(CServerListenerModule* thes) {
	int nAddressSize = sizeof(SOCKADDR);
	SOCKET sock = 0;
	CModule* e = thes->msg_executer;
	ST_NEW_CONNECT_REQ req = {{MSG_ID_NEW_CONNECT_REQ, sizeof(req) - sizeof(CMsg)}, 0};

	sock = accept(thes->socket_for_listen, (SOCKADDR *)&thes->Addr[thes->mCount], &nAddressSize);
	if (thes->mCount > WSA_MAXIMUM_WAIT_EVENTS) {
		closesocket(sock);
		return -1;
	}
	thes->EventList[thes->mCount] = WSACreateEvent();
	thes->socketList[thes->mCount] = sock;
	WSAEventSelect(thes->socketList[thes->mCount], thes->EventList[thes->mCount], FD_READ | FD_ACCEPT);
	//printf("ip %s Connect!\n", inet_ntop(thes->Addr[thes->mCount].sin_addr));
	TS_DEBUG("new Connect!");
	++thes->mCount;

	req.sock = sock;
	e->sendMsg(e, &req.msg);
	return 0;
}

static void sockerServerProcess(void* param) {
	CServerListenerModule* thes = (CServerListenerModule*)param;
	DWORD dwIndex = 0;
	WSANETWORKEVENTS wsaEvents = {0};
	while (1) {
		dwIndex = WSAWaitForMultipleEvents(thes->mCount, thes->EventList, FALSE, WSA_INFINITE, FALSE);
		if (WSA_WAIT_FAILED == dwIndex) {
			continue; //? 
		}
		memset(&wsaEvents, 0, sizeof(WSANETWORKEVENTS));
		WSAEnumNetworkEvents(thes->socketList[dwIndex - WSA_WAIT_EVENT_0], thes->EventList[dwIndex - WSA_WAIT_EVENT_0], &wsaEvents);
		if (wsaEvents.lNetworkEvents & FD_READ && 0 == wsaEvents.iErrorCode[FD_READ_BIT]) {
			receive_data(thes, &thes->socketList[dwIndex - WSA_WAIT_EVENT_0]);
		} else if (wsaEvents.lNetworkEvents & FD_ACCEPT && 0 == wsaEvents.iErrorCode[FD_ACCEPT_BIT]) {
			if (!on_new_client_connect(thes)) {
				continue;
			}
		}
	}
	return;
}

static int listener_run(struct _cserverlistener_module_* thes) {
	_beginthread(sockerServerProcess, 0, thes);
	return 0;
}

static int listener_init(CServerListenerModule* thes) {
	WSADATA              wsaData;
	SOCKADDR_IN          ServerAddr;

	WSAStartup(MAKEWORD(2, 2), &wsaData);
	thes->socket_for_listen = socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET == thes->socket_for_listen) {
		DEBUG_LOG("create socket failed.\n");
		return 0;
	}

	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(thes->listen_on_port);
	ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);

	if (SOCKET_ERROR == bind(thes->socket_for_listen, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr))) {
		DEBUG_LOG("bind listening socket port failed.\n");
		return 0;
	}

	HANDLE hEvent = WSACreateEvent();
	thes->socketList[0] = thes->socket_for_listen;
	thes->EventList[0] = hEvent;
	WSAEventSelect(thes->socket_for_listen, hEvent, FD_ACCEPT | FD_CLOSE);

	if (SOCKET_ERROR == listen(thes->socket_for_listen, 5)) {
		DEBUG_LOG("listen failed.\n");
		return 0;
	}
	TS_DEBUG("server init ok.");
	return 1;
}

int construct_server_listener(CServerListenerModule* thes, const char* module_name, unsigned short listen_on_port, CModule* msg_executer) {
	construct_module(&thes->parent, module_name);
	thes->msg_executer = msg_executer;
	thes->mCount = 1;
	thes->listen_on_port = listen_on_port;
	thes->run = listener_run;
	thes->send_msg_to_client = csocketmisc_send_msg;

	AS_MODULE(thes)->run(AS_MODULE(thes), USE_DEFAULT_MODULE_ENTRY);
	listener_init(thes);
	return 0;
}


